package com.ybg.bookmanages.services.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ybg.bookcommons.dto.BorrowBookDTO;
import com.ybg.bookmanages.commons.UploadUtil;
import com.ybg.bookmanages.mapper.BookinfosMapper;
import com.ybg.bookmanages.mapper.BorrowBooksMapper;
import com.ybg.bookmanages.mapper.DamageBooksMapper;
import com.ybg.bookmanages.mapper.UserinfosMapper;
import com.ybg.bookmanages.module.entity.Bookinfos;
import com.ybg.bookmanages.module.entity.BorrowBooks;
import com.ybg.bookmanages.module.entity.DamageBooks;
import com.ybg.bookmanages.module.entity.Userinfos;
import com.ybg.bookmanages.module.vo.BookinfosVO;
import com.ybg.bookmanages.services.BookinfosServcie;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;

@Service
public class BookinfosServiceImpl extends ServiceImpl<BookinfosMapper, Bookinfos>
        implements BookinfosServcie{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Value("${file.upload_dir}")
    private String uploadDir;
    @Resource
    private UploadUtil uploadUtil;
    @Resource
    private DamageBooksMapper damageBooksMapper;
    @Resource
    private BorrowBooksMapper borrowBooksMapper;
    @Resource
    private UserinfosMapper userinfosMapper;

    @Transactional
    @Override
    public boolean addBook(BookinfosVO bvo, MultipartFile file) {
        try {
            Path path = Paths.get(uploadDir);
            if(!Files.exists(path)){
                Files.createDirectory(path);
            }
            //将图片存储到临时文件目录
            String serverTmpImgPath=path.toAbsolutePath()
                    + File.separator+file.getOriginalFilename();
            File tmpImg = new File(serverTmpImgPath);
            file.transferTo(tmpImg);
            //将临时文件上传到fastdfs文件服务器
            String returnPath = uploadUtil.upload(serverTmpImgPath);
            //将服务器返回的文件路径保存到MySQL数据库中
            Bookinfos book = new Bookinfos();
            BeanUtils.copyProperties(bvo,book);
            book.setBookimage(returnPath);
            book.setDeleted(0);
            save(book);
            //删除临时文件
            tmpImg.delete();
            return true;
        } catch (IOException e) {
            logger.error("新增图书失败:"+e.getMessage());
            return false;
        }
    }

    @Override
    public boolean damageBook(String isbn,String damagereason) {
        try {
            //1.按照isbn查询图书编号
            QueryWrapper<Bookinfos> query = new QueryWrapper<>();
            query.eq("isbn",isbn);
            Bookinfos book = this.getOne(query);
            //2.将破损图书信息存放到破损表中
            DamageBooks damage = DamageBooks.builder()
                    .bookid(book.getBookid())
                    .damagedate(new Date())
                    .damagereason(damagereason)
                    .build();
            damageBooksMapper.insert(damage);
            //3.计算在库图书是否都已经破损
            QueryWrapper<DamageBooks> damageQuery = new QueryWrapper<>();
            damageQuery.eq("bookid",book.getBookid());
            Long damageNum = damageBooksMapper.selectCount(damageQuery);
            if(book.getStore().longValue()-damageNum.longValue()<=0) {
                //3.1 如果都已经破损则图书下架
                this.removeById(book.getBookid());
            }
            return true;
        } catch (Exception e) {
            logger.error("破损图书流程失败:"+e.getMessage());
            return false;
        }
    }

    @Override
    public boolean borrowBook(String isbn,String cardid) {
        //1.查询该图书当前库存
        Long store = this.getBaseMapper().selectBookCurrentStore(isbn);
        if(store.longValue()>0){
            //2.如果库存足够则向借阅表中插入数据
            LambdaQueryWrapper<Bookinfos> bookQuery = new LambdaQueryWrapper<>();
            bookQuery.eq(Bookinfos::getIsbn,isbn);
            Bookinfos book = this.getOne(bookQuery);
            LambdaQueryWrapper<Userinfos> userQuery = new LambdaQueryWrapper<>();
            userQuery.eq(Userinfos::getCardid,cardid);
            Userinfos us = userinfosMapper.selectOne(userQuery);
            LocalDate date = LocalDate.now();
            BorrowBooks borrow = BorrowBooks.builder().bookid(book.getBookid())
                    .userid(us.getUserid())
                    .borrowdate(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()))
                    .returndate(Date.from(date.plusDays(10).atStartOfDay(ZoneId.systemDefault()).toInstant()))
                    .build();
            int res = borrowBooksMapper.insert(borrow);
            System.out.println(borrow);
            if(res==0){
                return false;
            }else {
                return true;
            }
        }else {
            // 库存不足无法借阅
            return false;
        }

    }

    @Override
    public BorrowBookDTO backBook(String isbn, String cardid) {
        try {
            //1.根据图书isbn和cardid 查询 bookid和userid
            LambdaQueryWrapper<Bookinfos> bookQuery = new LambdaQueryWrapper<>();
            bookQuery.eq(Bookinfos::getIsbn,isbn);
            Bookinfos book = this.getOne(bookQuery);
            LambdaQueryWrapper<Userinfos> userQuery = new LambdaQueryWrapper<>();
            userQuery.eq(Userinfos::getCardid,cardid);
            Userinfos us = userinfosMapper.selectOne(userQuery);
            //2.根据bookid和userid查询借阅信息
            LambdaQueryWrapper<BorrowBooks> borrowQuery=new LambdaQueryWrapper();
            borrowQuery.eq(BorrowBooks::getUserid,us.getUserid()).eq(BorrowBooks::getBookid,book.getBookid());
            BorrowBooks recode = borrowBooksMapper.selectOne(borrowQuery);
            //3.计算用户借阅是否逾期 如逾期则计算罚款数
            LocalDate now = LocalDate.now();
            LocalDate returnDate = LocalDate.ofInstant(
                    recode.getReturndate().toInstant(), ZoneId.systemDefault());
            long days = ChronoUnit.DAYS.between(now, returnDate);
            recode.setRealbackdate(new Date());
            //判断是否应该逾期罚款
            if(days>=0){
                recode.setOverdue(0.0);
            }else{
                recode.setOverdue(Math.abs(days)*1.0);
            }
            //4.更新借阅信息
            borrowBooksMapper.updateById(recode);
            //将信息存放到BorrowBookDTO中
            BorrowBookDTO bbdto = BorrowBookDTO.builder()
                    .bookname(book.getBookname())
                    .build();
            BeanUtils.copyProperties(recode,bbdto);
            return bbdto;
        } catch (Exception e) {
            logger.error("归还图书异常:"+e.getMessage());
            return null;
        }
    }
}
